#ifndef _VN_MESSAGE_SYSTEM_H_
#define _VN_MESSAGE_SYSTEM_H_

#include <string>
#include <vector>
#include <map>

class Message;
class MessageSystem
{
public:
	class ISubjectCallback
	{
	public:
		virtual ~ISubjectCallback(){}
		virtual void notify(const std::string&, Message*) = 0;
		virtual bool isObject(void*) = 0;
	};

	template <class T>
	class SubjectCallback : public ISubjectCallback
	{
	public:
		T* m_object;
		void(T::*m_method)(const std::string&, Message*);
		SubjectCallback(T* p_object, void(T::*p_method)(const std::string&, Message*)) : m_object(p_object), m_method(p_method){};
		void notify(const std::string& p_subject, Message* p_data)
		{
			(*m_object.*m_method)(p_subject, p_data);
		}
		bool isObject(void* p_object)
		{
			return m_object == p_object;
		}
	};

	static MessageSystem& getSingleton();
	static void clean();

	template <class T>
	void registerSubject(const std::string& p_subject, T* p_object, void (T::*p_method)(const std::string&, Message*))
	{
		m_subjects[p_subject].push_back(new SubjectCallback<T>(p_object, p_method));
	}

	void unregister(const std::string& p_subject, void* p_object);
	void notify(const std::string& p_subject, Message* p_data);

private:
	MessageSystem(void);
	virtual ~MessageSystem(void);

	static MessageSystem* m_instance;

	typedef std::vector<ISubjectCallback*> CallbackList;
	typedef std::map<std::string, CallbackList> SubjectList;

	SubjectList m_subjects;

	inline void clearMessages();
};

#endif // _VN_MESSAGE_SYSTEM_H_